`include "defines.sv"

module renderer(
	input clk,
	input clock50,
	
	input [7:0] last_data_received,
	//input [7:0] ps2_key_data,
	
	input candraw,
	input [10:0] x,
	input [10:0] y,
	input [3:0] KEY,
	output reg [9:0] red,
	output reg [9:0] green,
	output reg [9:0] blue,
	output vga_blank
	);

	/*parameter start = 2'b00;
	parameter onfloor = 2'b01;
	parameter falldown = 2'b10;
	parameter dead = 2'b11;
	*/
	
	
	parameter start = 3'b000;
	parameter onfloor = 3'b001;
	parameter falldown = 3'b010;
	parameter dead = 3'b011;
	parameter pause = 3'b100;
	parameter start_screen = 3'b101;
	
	
	//keyboard control(PS2_CLK, PS2_DAT, clock50, KEY[2], read, scan_ready, scan_code);
	
	reg [31:0] count_down, counter_H_Left, counter_H_Right, counter_V, counter_GoUp, counter_ac, speed;
	reg [1:0] S, NS;
	reg [10:0] brick1_H_SYNC, brick2_H_SYNC, brick3_H_SYNC, brick4_H_SYNC, brick5_H_SYNC;
	reg [10:0] brick1_V_SYNC, brick2_V_SYNC, brick3_V_SYNC, brick4_V_SYNC, brick5_V_SYNC;
	reg [10:0] oVGA_H_SYNC, oVGA_V_SYNC, brick_H_SYNC, brick_V_SYNC;
	
	reg [9:0] R, R_deadblock;
	//RanGen random(KEY[2], clk, brick1_H_SYNC, R);
	always@(posedge clk or negedge KEY[2])
	begin
		if(!KEY[2])
		begin
			R <= brick5_H_SYNC;    /*load the initial value when load is active*/
		end
		else
		begin
			R[0] <= R[9];
			R[1] <= R[0];
			R[2] <= R[1];
			R[3] <= R[2];
			R[4] <= R[3];
			R[5] <= R[4];
			R[6] <= R[5]^R[9];
			R[7] <= R[6]^R[9];
			R[8] <= R[7]^R[9];
			R[9] <= R[8];
		end			
	end
	
	always@(posedge clk or negedge KEY[2])
	begin
		if(!KEY[2])
		begin
			R_deadblock <= brick5_H_SYNC/2;    /*load the initial value when load is active*/
		end
		else
		begin
			R_deadblock[0] <= R_deadblock[9];
			R_deadblock[1] <= R_deadblock[0];
			R_deadblock[2] <= R_deadblock[1];
			R_deadblock[3] <= R_deadblock[2];
			R_deadblock[4] <= R_deadblock[3];
			R_deadblock[5] <= R_deadblock[4];
			R_deadblock[6] <= R_deadblock[5]^R_deadblock[9];
			R_deadblock[7] <= R_deadblock[6]^R_deadblock[9];
			R_deadblock[8] <= R_deadblock[7]^R_deadblock[9];
			R_deadblock[9] <= R_deadblock[8];
		end			
	end
	
	/*always @(*)
	begin
		if((R >= 10'd10 && R <= 10'd30)||
			(R >= 10'd110 && R <= 10'd130)||
			(R >= 10'd210 && R <= 10'd230)||
			(R >= 10'd310 && R <= 10'd330)||
			(R >= 10'd410 && R <= 10'd430)||
			(R >= 10'd510 && R <= 10'd530)||
			(R >= 10'd610 && R <= 10'd630)||
			(R >= 10'd710 && R <= 10'd730)||
			(R >= 10'd810 && R <= 10'd830)||
			(R >= 10'd910 && R <= 10'd930))
		begin
			R = R_deadblock;
		end
	end*/

	
	always @(posedge clk or negedge KEY[2])
	begin
		if(KEY[2] == 1'b0)
		begin
			count_down <= 32'd0;
		end
		else
		begin
			if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h6))
			begin
				count_down <= 32'd0;
			end
			else
				begin
				if(count_down < 32'd540000000)
				begin
					count_down <= count_down +1'b1;
				end
				else
				begin
					count_down <= 32'd1080000000;
				end
			end	
		end
	end
	
	
	always @(posedge clk or negedge KEY[2])
	begin
		if(KEY[2] == 1'b0)
		begin
			speed <= 32'd0;
		end
		else
		begin
		
			if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h6))
			begin
				speed <= 32'd0;
			end
			else
			begin
		
				if(counter_ac <= 32'd540000000)
				begin
					counter_ac <= counter_ac + 32'd1;
				end
				else
				begin
					counter_ac <= 32'd0;
					if(speed < 32'd425000)
					begin
						speed <= speed + 32'd25000;
					end
					else
					begin
						speed <= 32'd425000;
					end
				end
			end
		end
	end
	
	always @(*)
	begin
		case(S)
			start:
			begin
				if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h4)||(last_data_received[7:4] == 8'h6 && last_data_received[3:0] == 8'hb))
				begin
					NS = falldown;
				end
				else
				begin
					NS = start;
				end
			end
			onfloor:
			begin
			
				if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h6))
				begin
					NS = start;
				end
				else
				begin
					if(oVGA_V_SYNC > 11'd30 && oVGA_V_SYNC < 11'd994)
					begin
						if((oVGA_H_SYNC > (brick_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick_H_SYNC + 11'd90)))
						begin
						
							/*if((R >= 10'd10 && R <= 10'd30)||
								(R >= 10'd110 && R <= 10'd130)||
								(R >= 10'd210 && R <= 10'd230)||
								(R >= 10'd310 && R <= 10'd330)||
								(R >= 10'd410 && R <= 10'd430)||
								(R >= 10'd510 && R <= 10'd530)||
								(R >= 10'd610 && R <= 10'd630)||
								(R >= 10'd710 && R <= 10'd730)||
								(R >= 10'd810 && R <= 10'd830)||
								(R >= 10'd910 && R <= 10'd930)&&
								(brick_H_SYNC == (R_deadblock + 11'd90))&&
								(count_down == 32'd1080000000))
							begin
								NS = dead;
							end
							else
							begin*/
							
								NS = onfloor;
								
							//end
							
						end
						else
						begin
							NS = falldown;
						end
					end
					else
					begin
						NS = dead;
					end
					
				end	
				
			end
			falldown:
			begin
			
				if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h6))
				begin
					NS = start;
				end
				else
				begin
			
					if(oVGA_V_SYNC > 11'd30 && oVGA_V_SYNC < 11'd994)
					begin
						if((oVGA_V_SYNC == brick1_V_SYNC - 11'd40) && (oVGA_H_SYNC > (brick1_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick1_H_SYNC + 11'd90)))
						begin
							brick_H_SYNC = brick1_H_SYNC;
							NS = onfloor;
							brick_V_SYNC = brick1_V_SYNC;
						end
						else if((oVGA_V_SYNC == brick2_V_SYNC - 11'd40) && (oVGA_H_SYNC > (brick2_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick2_H_SYNC + 11'd90)))
						begin
							brick_H_SYNC = brick2_H_SYNC;
							NS = onfloor;
							brick_V_SYNC = brick2_V_SYNC;
						end
						else if((oVGA_V_SYNC == brick3_V_SYNC - 11'd40) && (oVGA_H_SYNC > (brick3_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick3_H_SYNC + 11'd90)))
						begin
							brick_H_SYNC = brick3_H_SYNC;
							NS = onfloor;
							brick_V_SYNC = brick3_V_SYNC;
						end
						else if((oVGA_V_SYNC == brick4_V_SYNC - 11'd40) && (oVGA_H_SYNC > (brick4_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick4_H_SYNC + 11'd90)))
						begin
							brick_H_SYNC = brick4_H_SYNC;
							NS = onfloor;
							brick_V_SYNC = brick4_V_SYNC;
						end
							
						else if((oVGA_V_SYNC == brick5_V_SYNC - 11'd40) && (oVGA_H_SYNC > (brick5_H_SYNC - 11'd90)) && (oVGA_H_SYNC < (brick5_H_SYNC + 11'd90)))
						begin
							brick_H_SYNC = brick5_H_SYNC;
							NS = onfloor;
							brick_V_SYNC = brick5_V_SYNC;
						end
							
						else
						begin
							NS = falldown;
						end
					end
					
					else if(oVGA_V_SYNC == 11'd30)
					begin
						NS = dead;
					end
					else
					begin
						NS = dead;
					end
				
				end
				
			end
			dead:
			begin
				if(KEY[2] == 1'b0)
				begin
					NS = start;
				end
				else
				begin
					
					if((last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h6))
					begin
						NS = start;
					end
					else
					begin
					
					NS = dead;
					end
				end
			end
			/*pause:
			begin
				if((key[1]|key[0]) == 1'b1)
				begin
					NS = falldown;
				end
				else if(key[2] == 1'b1)
				begin
					NS = start;
				end
				else
				begin
					NS = pause;
				end
			end*/
		endcase
	end
	
	always @(posedge clk or negedge KEY[2])
	begin
		if(KEY[2] == 1'b0)
		begin
			S <= start;
		end
		else
			begin
				S <= NS;
			end
	end
	always @(posedge clk or negedge KEY[2])
	begin
		if(KEY[2] == 1'b0)
		begin
			brick1_V_SYNC <= 11'd250;
			brick2_V_SYNC <= 11'd400;
			brick3_V_SYNC <= 11'd600;
			brick4_V_SYNC <= 11'd800;
			brick5_V_SYNC <= 11'd1000;
			brick1_H_SYNC <= 11'd190;
			brick2_H_SYNC <= 11'd300;
			brick3_H_SYNC <= 11'd600;
			brick4_H_SYNC <= 11'd500;
			brick5_H_SYNC <= 11'd900;
			oVGA_V_SYNC <= 11'd210;
			oVGA_H_SYNC <= 11'd190;	
		end
		else
		begin
			case(S)
				start:
				begin
					brick1_V_SYNC <= 11'd250;
					brick2_V_SYNC <= 11'd400;
					brick3_V_SYNC <= 11'd600;
					brick4_V_SYNC <= 11'd800;
					brick5_V_SYNC <= 11'd1000;
					brick1_H_SYNC <= 11'd190;
					brick2_H_SYNC <= 11'd300;
					brick3_H_SYNC <= 11'd600;
					brick4_H_SYNC <= 11'd500;
					brick5_H_SYNC <= 11'd900;
					
					oVGA_V_SYNC <= 11'd210;
					oVGA_H_SYNC <= 11'd190;	
					
				end
				onfloor:
				begin
					if(counter_GoUp <= (32'd421875 - speed))
					
					begin
						counter_GoUp <= counter_GoUp + 1'b1;
					end
					else
					begin
						counter_GoUp <= 32'd0;
						brick1_V_SYNC <= brick1_V_SYNC - 11'd1;
						brick2_V_SYNC <= brick2_V_SYNC - 11'd1;
						brick3_V_SYNC <= brick3_V_SYNC - 11'd1;
						brick4_V_SYNC <= brick4_V_SYNC - 11'd1;
						brick5_V_SYNC <= brick5_V_SYNC - 11'd1;
						oVGA_V_SYNC <= oVGA_V_SYNC - 11'd1;
						
						if(brick1_V_SYNC == 10)
						begin
							brick1_H_SYNC <= brick2_H_SYNC;
							brick1_V_SYNC <= brick2_V_SYNC;
							brick2_H_SYNC <= brick3_H_SYNC;
							brick2_V_SYNC <= brick3_V_SYNC;
							brick3_H_SYNC <= brick4_H_SYNC;
							brick3_V_SYNC <= brick4_V_SYNC;
							brick4_H_SYNC <= brick5_H_SYNC;
							brick4_V_SYNC <= brick5_V_SYNC;
							/*if((R >= 10'd10 && R <= 10'd30)||
							   (R >= 10'd110 && R <= 10'd130)||
							   (R >= 10'd210 && R <= 10'd230)||
							   (R >= 10'd310 && R <= 10'd330)||
							   (R >= 10'd410 && R <= 10'd430)||
							   (R >= 10'd510 && R <= 10'd530)||
							   (R >= 10'd610 && R <= 10'd630)||
							   (R >= 10'd710 && R <= 10'd730)||
							   (R >= 10'd810 && R <= 10'd830)||
							   (R >= 10'd910 && R <= 10'd930)&&
								(count_down == 32'd1080000000))
							begin
								brick5_H_SYNC <= R_deadblock + 11'd90;
							end
							else
							begin*/
								brick5_H_SYNC <= R + 11'd90;
							//end
							brick5_V_SYNC <= 11'd1014; 
						end
					end
				
				
					if(/*KEY[0] == 1'b0 && KEY[1] != 1'b0*/last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h4)
					begin
					
					
						if(counter_H_Right < 32'd337500)
						begin
							counter_H_Right <= counter_H_Right + 1'b1;
						end
						else
						begin
							counter_H_Right <= 32'd0;
							oVGA_H_SYNC <= oVGA_H_SYNC + 11'd1;
							if(oVGA_H_SYNC >= 11'd1270)
							begin
								oVGA_H_SYNC <= 11'd10;
							end
						end
					end
					else if(/*KEY[1] == 1'b0 && KEY[0] !=1'b0*/last_data_received[7:4] == 8'h6 && last_data_received[3:0] == 8'hb)
					begin
					
					
						if(counter_H_Left < 32'd337500)
						begin
							counter_H_Left <= counter_H_Left + 1'b1;
						end
						else
						begin
							counter_H_Left <= 32'd0;
							oVGA_H_SYNC <= oVGA_H_SYNC - 1'b1;
							if(oVGA_H_SYNC <= 11'd10)
							begin
								oVGA_H_SYNC <= 11'd1270;
							end
						end
					end
				end
				falldown:
				begin
					if(brick1_V_SYNC == 10)
					begin
						brick1_H_SYNC <= brick2_H_SYNC;
						brick1_V_SYNC <= brick2_V_SYNC;
						brick2_H_SYNC <= brick3_H_SYNC;
						brick2_V_SYNC <= brick3_V_SYNC;
						brick3_H_SYNC <= brick4_H_SYNC;
						brick3_V_SYNC <= brick4_V_SYNC;
						brick4_H_SYNC <= brick5_H_SYNC;
						brick4_V_SYNC <= brick5_V_SYNC;
						/*if((R >= 10'd10 && R <= 10'd30)||
							   (R >= 10'd110 && R <= 10'd130)||
							   (R >= 10'd210 && R <= 10'd230)||
							   (R >= 10'd310 && R <= 10'd330)||
							   (R >= 10'd410 && R <= 10'd430)||
							   (R >= 10'd510 && R <= 10'd530)||
							   (R >= 10'd610 && R <= 10'd630)||
							   (R >= 10'd710 && R <= 10'd730)||
							   (R >= 10'd810 && R <= 10'd830)||
							   (R >= 10'd910 && R <= 10'd930)&&
								(count_down == 32'd1080000000))
						begin
							brick5_H_SYNC <= R_deadblock + 11'd90;
						end
						else
						begin*/
							brick5_H_SYNC <= R + 11'd90;
						//end
						brick5_V_SYNC <= 11'd1014; 
					end
					
					//if(counter_GoUp <= 32'd421875)
					if(counter_GoUp <= (32'd421875 - speed))
					
					begin
						counter_GoUp <= counter_GoUp + 1'b1;
					end
					else
					begin
						counter_GoUp <= 32'd0;
						
						brick1_V_SYNC <= brick1_V_SYNC - 11'd1;
						brick2_V_SYNC <= brick2_V_SYNC - 11'd1;
						brick3_V_SYNC <= brick3_V_SYNC - 11'd1;
						brick4_V_SYNC <= brick4_V_SYNC - 11'd1;
						brick5_V_SYNC <= brick5_V_SYNC - 11'd1;
						
					end
					
					
					if(counter_V <= 32'd506250)
					begin
						counter_V <= counter_V + 1'b1;
					end
					else
					begin
						counter_V <= 32'd0;
						oVGA_V_SYNC <= oVGA_V_SYNC + 11'd1;
					end
					if(/*KEY[0] == 1'b0 && KEY[1] != 1'b0*/last_data_received[7:4] == 8'h7 && last_data_received[3:0] == 8'h4)
					begin
					
					
						if(counter_H_Right < 32'd337500)
						begin
							counter_H_Right <= counter_H_Right + 1'b1;
						end
						else
						begin
							counter_H_Right <= 32'd0;
							oVGA_H_SYNC <= oVGA_H_SYNC + 11'd1;
							if(oVGA_H_SYNC >= 11'd1270)
							begin
								oVGA_H_SYNC <= 11'd10;
							end
						end
					end
					else if(/*KEY[1] == 1'b0 && KEY[0] !=1'b0*/last_data_received[7:4] == 8'h6 && last_data_received[3:0] == 8'hb)
					begin
					
					
						if(counter_H_Left < 32'd337500)
						begin
							counter_H_Left <= counter_H_Left + 1'b1;
						end
						else
						begin
							counter_H_Left <= 32'd0;
							oVGA_H_SYNC <= oVGA_H_SYNC - 1'b1;
							if(oVGA_H_SYNC <= 11'd10)
							begin
								oVGA_H_SYNC <= 11'd1270;
							end
						end
					end
				end
				dead:
				begin
					oVGA_H_SYNC <= 11'd640;
					oVGA_V_SYNC <= 11'd480;
				end
				//pause:
				
			endcase
		end
	end
	
	reg n_vga_blank;
	assign vga_blank = !n_vga_blank;
	
	/*always @(posedge clk) begin
		if (candraw) begin
		    n_vga_blank <= 1'b0;
			
			// output a red rectangle in the middle of the screen
			if (x > 1180 && x < 1280 && y > 100 && y < 200) begin
				red 	<= 10'b11_1111_1111;
				green 	<= 10'd0;
				blue	<= 10'd0;
				end
			// with a blue background
				else begin
				red		<= 10'd0;
				green	<= 10'd0;
				blue	<= 10'b11_1111_1111;
			end
		end else begin
			// if we are not in the visible area, we must set the screen blank
			n_vga_blank <= 1'b1;
		end
	end*/
	
	always @(posedge clk) 
	begin
		if (candraw) 
		begin
			n_vga_blank <= 1'b0;
			
				// output a red rectangle in the middle of the screen
				if ((x > oVGA_H_SYNC - 11'd10 && x < oVGA_H_SYNC + 11'd10 && y > oVGA_V_SYNC - 11'd30 && y < oVGA_V_SYNC + 11'd30)||
					 (x > brick1_H_SYNC - 11'd80 && x < brick1_H_SYNC + 11'd80 && y > brick1_V_SYNC - 11'd10 && y < brick1_V_SYNC + 11'd10)||
					 (x > brick2_H_SYNC - 11'd80 && x < brick2_H_SYNC + 11'd80 && y > brick2_V_SYNC - 11'd10 && y < brick2_V_SYNC + 11'd10)||
					 (x > brick3_H_SYNC - 11'd80 && x < brick3_H_SYNC + 11'd80 && y > brick3_V_SYNC - 11'd10 && y < brick3_V_SYNC + 11'd10)||
					 (x > brick4_H_SYNC - 11'd80 && x < brick4_H_SYNC + 11'd80 && y > brick4_V_SYNC - 11'd10 && y < brick4_V_SYNC + 11'd10)||
					 (x > brick5_H_SYNC - 11'd80 && x < brick5_H_SYNC + 11'd80 && y > brick5_V_SYNC - 11'd10 && y < brick5_V_SYNC + 11'd10)) 
				begin
					red 	<= 10'b11_1111_1111;
					green <= 10'd0;
					blue	<= 10'd0;
					//red 	<= 10'd11_1111_1111;
					//green 	<= 10'd11_1111_1111;
					//blue	<= 10'd11_1111_1111;
				end
				// with a blue background
				else 
				begin
					red	<= 10'd0;
					green	<= 10'd0;
					blue  <= 10'd0;
					
				end
		end 
		else 
		begin
			// if we are not in the visible area, we must set the screen blank
			n_vga_blank <= 1'b1;
		end
	end
	
endmodule 